package cn.com.dhcc.app.pub.core.util;

import java.io.*;   
import java.util.StringTokenizer;   

public class CPUReader {
	
	
	private static final int CPUTIME = 30;   
	  
    private static final int PERCENT = 100;   
  
    private static final int FAULTLENGTH = 10;   
     
    //TODO: get linux version!!
    private static String linuxVersion = ""; 
    
	public static float getCPURatio() throws IOException, InterruptedException, NumberFormatException {
		String os_name = System.getProperty("os.name");
		
		float cpuRatio = 0;   
        if (os_name.toLowerCase().startsWith("windows")) {   
            cpuRatio = getCpuRatioForWindows();   
        }   
        else {   
        	cpuRatio = getCpuRateForLinux();   
        }
        
        return cpuRatio;
	}
	
	private static float getCpuRatioForWindows() throws IOException, InterruptedException,NumberFormatException {		 
		 String procCmd = System.getenv("windir")   
                 + "\\system32\\wbem\\wmic.exe process get Caption,CommandLine,"   
                 + "KernelModeTime,ReadOperationCount,ThreadCount,UserModeTime,WriteOperationCount";   
         // 取进程信息   
         long[] c0 = readCpu(Runtime.getRuntime().exec(procCmd));   
         Thread.sleep(CPUTIME);   
         long[] c1 = readCpu(Runtime.getRuntime().exec(procCmd));   
         if (c0 != null && c1 != null) {   
             long idletime = c1[0] - c0[0];   
             long busytime = c1[1] - c0[1];
             
             return PERCENT * busytime/(busytime + idletime);
         } else {   
             return 0;   
         }   
	}
	
	/**
	 * 读取CPU信息.
	 * 
	 * @param proc
	 * @throws Exception 
	 */
	private static long[] readCpu(final Process proc) throws IOException, NumberFormatException {   
		long[] retn = new long[2];

		try {
			proc.getOutputStream().close();
			InputStreamReader ir = new InputStreamReader(proc.getInputStream());
			LineNumberReader input = new LineNumberReader(ir);
			String line = input.readLine();
			if (line == null || line.length() < FAULTLENGTH) {
				return null;
			}
			int capidx = line.indexOf("Caption");
			int cmdidx = line.indexOf("CommandLine");
			int rocidx = line.indexOf("ReadOperationCount");
			int umtidx = line.indexOf("UserModeTime");
			int kmtidx = line.indexOf("KernelModeTime");
			int wocidx = line.indexOf("WriteOperationCount");
			long idletime = 0;
			long kneltime = 0;
			long usertime = 0;
			while ((line = input.readLine()) != null) {
				if (line.length() < wocidx) {
					continue;
				}
				// 字段出现顺序：Caption,CommandLine,KernelModeTime,ReadOperationCount,
				// ThreadCount,UserModeTime,WriteOperation
				String caption = Bytes.substring(line, capidx, cmdidx - 1)
						.trim();
				String cmd = Bytes.substring(line, cmdidx, kmtidx - 1).trim();
				if (cmd.indexOf("wmic.exe") >= 0) {
					continue;
				}
				String s1 = Bytes.substring(line, kmtidx, rocidx - 1).trim();
				String s2 = Bytes.substring(line, umtidx, wocidx - 1).trim();
				if (caption.equals("System Idle Process")
						|| caption.equals("System")) {
					if (s1.length() > 0)
						idletime += Long.valueOf(s1).longValue();
					if (s2.length() > 0)
						idletime += Long.valueOf(s2).longValue();
					continue;
				}
				if (s1.length() > 0)
					kneltime += Long.valueOf(s1).longValue();
				if (s2.length() > 0)
					usertime += Long.valueOf(s2).longValue();
			}
			retn[0] = idletime;
			retn[1] = kneltime + usertime;
			return retn;
		} catch (IOException ex) {
			throw ex;
		} catch (NumberFormatException e) {
			throw e;
		} finally {
			try {
				proc.getInputStream().close();
			} catch (IOException ex) {
				throw new IOException(ex);
			}
		}

	}
	
	/**
	 * Get linux version
	 * 
	 * @return Linux Version
	 * @throws IOException
	 */
	private static String getLinuxVersion() throws IOException {
		String fullVersion = System.getProperty("os.version");
		int indexOfSecondPoint = fullVersion.indexOf(".", fullVersion.indexOf(".") + 1);
		String version = fullVersion.substring(0, indexOfSecondPoint);
		return version;
	}
	
	private static float getCpuRateForLinux(){   
		InputStream is = null;  
        InputStreamReader isr = null;  
        BufferedReader brStat = null;  
        StringTokenizer tokenStat = null; 
       
        try {  
        	linuxVersion =  getLinuxVersion(); 
            Process process = Runtime.getRuntime().exec("top -b -n 1");  
            is = process.getInputStream();  
            isr = new InputStreamReader(is);  
            brStat = new BufferedReader(isr);  
            if (linuxVersion.equals("2.4")) {  
                brStat.readLine();  
                brStat.readLine();  
                brStat.readLine();  
                brStat.readLine();  
                tokenStat = new StringTokenizer(brStat.readLine());  
                tokenStat.nextToken();  
                tokenStat.nextToken();  
                String user = tokenStat.nextToken();  
                tokenStat.nextToken();  
                String system = tokenStat.nextToken();  
                tokenStat.nextToken();  
                String nice = tokenStat.nextToken();  
                System.out.println(user + " , " + system + " , " + nice);    
                float userUsage = new Float(user).floatValue();  
                float systemUsage = new Float(system).floatValue();  
                float niceUsage = new Float(nice).floatValue();  
                return userUsage + systemUsage + niceUsage;  
            } else {  
                brStat.readLine();  
                brStat.readLine();  
                tokenStat = new StringTokenizer(brStat.readLine());  
                tokenStat.nextToken();  
                tokenStat.nextToken();  
                tokenStat.nextToken();  
                tokenStat.nextToken();  
                tokenStat.nextToken();  
                tokenStat.nextToken();  
                tokenStat.nextToken();  
                String cpuUsage = tokenStat.nextToken();  
                Float usage = new Float(cpuUsage);  
                return 100 - usage;
            }  
        } catch (IOException ioe) {  
            System.out.println(ioe.getMessage());  
            freeResource(is, isr, brStat);  
            return 1;  
        } finally {  
            freeResource(is, isr, brStat);  
        }  
  
    }   
	
	private static void freeResource(InputStream is, InputStreamReader isr, BufferedReader br){   
        try{   
            if(is!=null)   
                is.close();   
            if(isr!=null)   
                isr.close();   
            if(br!=null)   
                br.close();   
        }catch(IOException ioe){   
            System.out.println(ioe.getMessage());   
        }   
    }   
	
	private static class Bytes {  
	    /** *//** 
	     * 由于String.subString对汉字处理存在问题（把一个汉字视为一个字节)，因此在 
	     * 包含汉字的字符串时存在隐患，现调整如下： 
	     * @param src 要截取的字符串 
	     * @param start_idx 开始坐标（包括该坐标) 
	     * @param end_idx   截止坐标（包括该坐标） 
	     * @return 
	     */  
	    public static String substring(String src, int start_idx, int end_idx){  
	    	byte[] b = src.getBytes();  
	        String tgt = "";  
	        for (int i = start_idx; i <= end_idx; i++) {  
	            tgt += (char) b[i];  
	        }  
	        return tgt;
	    }  
	}  
	
	public static void main(String[] args) {
		try {
			System.out.println(getCPURatio());
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

}
